module StackOverflow
  module Questions
    using ExtensionString
    extend Engine
    class << self
      def add_class(klass, *args)
        eval <<-init
          class #{klass.capitalize}
            attr_reader :#{args.join(', :')}
            def initialize(#{args.join(', ')})
            #{args.map {|e| "@#{e} = #{e};"}.join}
            end
          end
        init
      end

      def [](q_index)
        return nil unless q_index.is_a? Integer
        html = Utils.http_get("/questions/#{q_index}")
        href = html.css('a').first.attr('href')
        arr = href.split('/')
        return nil unless q_index == arr[2].to_i
        html = Utils.http_get(href)
        q_title = html.css('div[id=question-header]').first.css('a').text
        question = html.css('div[class=question]').first
        q_detail = question.css('div[class=post-text]').text.strip
        q_vote = question.css('span[class~=vote-count-post]').text.to_i
        list = question.css('div[class=post-taglist]')
        q_labels = list.first.children.css('a').map {|e| e.text}
        q_comments = question.css('td[class=comment-text]').map {|e| e.text.strip}

        answers = html.css('div[class~=answer]').map do |e|
          a_index = e.attr('id')[7..-1].to_i
          a_detail = e.css('div[class=post-text]').text.strip
          a_accepted = e.attr('class').index('accepted-answer') ? true : false
          a_vote = e.css('span[class~=vote-count-post]').text.to_i
          a_comments = e.css('td[class=comment-text]').map {|t| t.text.strip}
          Answer.new(a_index, a_detail, a_accepted, a_vote, a_comments)
        end
        Question.new(q_index, "#{Utils::DOMAIN}#{href}",
                     q_title, q_detail, q_vote, q_labels, q_comments,
                     answers)
      end

      alias :at :[]

      def search(cond, engine = Native)
        return nil unless cond.is_a? String
        case engine
        when Native
          html = Utils.http_get("/search?q=#{cond.escape!}")
          results = html.css('div[class~=search-result]')
          results.map do |r|
            r_index = r.attr('id')[17..-1].to_i
            r_title = r.css('div[class=result-link]').text.strip
            r_abstract = r.css('div[class=excerpt]').text.strip
            r_vote = r.css('span[class~=vote-count-post]').text.to_i
            r_answer_count = r.css('div[class~=answered-accepted]').text.to_i
            Result.new(r_index, r_title, r_abstract, r_vote, r_answer_count)
          end
        when Github
          #TODO
          fail InvalidSearchEngine
        else
          fail InvalidSearchEngine
        end
      end
    end

    add_class :Question, :id, :url, :title, :detail, :vote, :labels, :comments, :answers
    add_class :Answer, :id, :detail, :accepted, :vote, :comments
    #TODO
    #add_class :Comment
    add_class :Result, :id, :title, :abstract, :vote, :answer_count
  end
end
